﻿
Imports System.Net
Imports System.Net.Sockets
Imports std

Public Class dnscache_t
    Private Const cachesize As Int64 = 1024
    Private Shared ReadOnly retireticks As Int64 = secondsToTicks(30 * 60)

    Private cache As cacheManager(Of String, vector(Of IPAddress)) = Nothing

    Public Sub New()
        cache = New cacheManager(Of String, vector(Of IPAddress)) _
                                (threadsafe:=True, cachesize:=cachesize, retireticks:=retireticks)
    End Sub

    Protected Overridable Function selectAddress(ByVal address As IPAddress) As Boolean
        Return Not address Is Nothing
    End Function

    Private Function resolveImpl(ByVal host As String) As vector(Of IPAddress)
        Dim entry As IPHostEntry = Nothing
        Try
            entry = Dns.GetHostEntry(host)
        Catch ex As Exception
            raiseError(errorHandle.errorType.system, "cannot resolve host ", host, ", ex ", ex.Message)
            Return Nothing
        End Try
        Dim rtn As vector(Of IPAddress) = Nothing
        If Not entry Is Nothing AndAlso Not entry.AddressList Is Nothing AndAlso entry.AddressList.Length() > 0 Then
            rtn = New vector(Of IPAddress)()
            Dim i As Int64
            For i = 0 To entry.AddressList.Length() - 1
                If selectAddress(entry.AddressList(i)) Then
                    rtn.push_back(entry.AddressList(i))
                End If
            Next
        End If

        Return rtn
    End Function

    Public Function resolve(ByVal host As String, Optional ByVal forceUpdate As Boolean = False) As vector(Of IPAddress)
        Dim ips As vector(Of IPAddress) = Nothing
        If forceUpdate OrElse Not cache.get(host, ips) Then
            ips = resolveImpl(host)
            If Not ips Is Nothing AndAlso ips.size() > 0 Then
                cache.add(host, ips)
            End If
        End If

        Return ips
    End Function

    Public Function resolveAsString(ByVal host As String,
                                    Optional ByVal forceUpdate As Boolean = False) As vector(Of String)
        Dim tmp As vector(Of IPAddress) = Nothing
        tmp = resolve(host, forceUpdate)
        If tmp Is Nothing Then
            Return Nothing
        Else
            Dim rtn As vector(Of String) = Nothing
            rtn = New vector(Of String)()
            For i As Int64 = 0 To tmp.size() - 1
                rtn.push_back(Convert.ToString(tmp(i)))
            Next
            Return rtn
        End If
    End Function

    Default Public ReadOnly Property at(ByVal host As String) As vector(Of IPAddress)
        Get
            Return resolve(host)
        End Get
    End Property
End Class

Public Class ipv4dnscache_t
    Inherits dnscache_t

    Protected Overrides Function selectAddress(ByVal address As IPAddress) As Boolean
        Return MyBase.selectAddress(address) AndAlso address.AddressFamily = AddressFamily.InterNetwork
    End Function
End Class

Public Module _dnscache
    Public ReadOnly dnscache As dnscache_t = Nothing
    Public ReadOnly ipv4dnscache As ipv4dnscache_t = Nothing

    Sub New()
        dnscache = New dnscache_t()
        ipv4dnscache = New ipv4dnscache_t()
    End Sub
End Module
